//Given an integer array nums, return an array answer such that answer[i] is equ
//al to the product of all the elements of nums except nums[i]. 
//
// The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit 
//integer. 
//
// You must write an algorithm that runs in O(n) time and without using the divi
//sion operation. 
//
// 
// Example 1: 
// Input: nums = [1,2,3,4]
//Output: [24,12,8,6]
// Example 2: 
// Input: nums = [-1,1,0,-3,3]
//Output: [0,0,9,0,0]
// 
// 
// Constraints: 
//
// 
// 2 <= nums.length <= 105 
// -30 <= nums[i] <= 30 
// The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit 
//integer. 
// 
//
// 
// Follow up: Can you solve the problem in O(1) extra space complexity? (The out
//put array does not count as extra space for space complexity analysis.) 
// Related Topics 数组 前缀和 
// 👍 922 👎 0


package leetcode.editor.cn;

import java.util.Arrays;

//Java：Product of Array Except Self
class P238ProductOfArrayExceptSelf {
    public static void main(String[] args) {
        Solution solution = new P238ProductOfArrayExceptSelf().new Solution();
        int[] ints = solution.productExceptSelf(new int[]{1, 2, 3, 4});
        System.out.println(Arrays.asList(ints));
        // TO TEST
    }

    //leetcode submit region begin(Prohibit modification and deletion)
    class Solution {
        public int[] productExceptSelf(int[] nums) {
            int len = nums.length;
            int[] suffix = new int[len];
            int[] prefix = new int[len];
            prefix[0] = nums[0];
            suffix[len - 1] = nums[len - 1];
            for (int i = 1; i < len; i++) {
                prefix[i] = prefix[i - 1] * nums[i];
            }
            for (int i = len - 2; i >= 0; i--) {
                suffix[i] = suffix[i + 1] * nums[i];
            }
            int[] res = new int[len];
            for (int i = 0; i < len; i++) {
                if (i == 0) {
                    res[i] = suffix[i + 1];
                } else if (i == len - 1) {
                    res[i] = prefix[i - 1];
                } else {
                    res[i] = suffix[i + 1] * prefix[i - 1];
                }
            }
            return res;
        }

        public int[] productExceptSelfA(int[] nums) {
            int length = nums.length;
            int[] answer = new int[length];

            // answer[i] 表示索引 i 左侧所有元素的乘积
            // 因为索引为 '0' 的元素左侧没有元素， 所以 answer[0] = 1
            answer[0] = 1;
            for (int i = 1; i < length; i++) {
                answer[i] = nums[i - 1] * answer[i - 1];
            }

            // R 为右侧所有元素的乘积
            // 刚开始右边没有元素，所以 R = 1
            int R = 1;
            for (int i = length - 1; i >= 0; i--) {
                // 对于索引 i，左边的乘积为 answer[i]，右边的乘积为 R
                answer[i] = answer[i] * R;
                // R 需要包含右边所有的乘积，所以计算下一个结果时需要将当前值乘到 R 上
                R *= nums[i];
            }
            return answer;
        }

    }
//leetcode submit region end(Prohibit modification and deletion)

}